package com.lgCore.server.invok.impl;

import com.esotericsoftware.reflectasm.MethodAccess;
import com.lgCore.server.invok.ICommonRpcRouteService;
import com.lgCore.server.invok.bean.RpcMethodInfo;
import com.lgCore.server.invok.bean.RpcRouteInfo;
import com.lgCore.server.invok.invokBean.InvokRpcMethod;
import com.lgCore.util.ClassUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class ICommonRpcRouteServiceImpl implements ICommonRpcRouteService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ICommonRpcRouteServiceImpl.class);

    //存放所有接口缓存
    public static ConcurrentHashMap<String, RpcRouteInfo> rpcRouteInfoConcurrentHashMap = new ConcurrentHashMap<>();


    @Override
    public void initServiceMethod(ApplicationContext applicationContext, String servicePack) {
        try {
            //检索所有包名
            Set<Class<?>> allClassSet = ClassUtil.getClasses(servicePack);
            Set<Class<?>> classSet = new HashSet<>();
            //剔除非接口类
            for (Class<?> t : allClassSet) {
                if (t.isInterface()) {
                    classSet.add(t);
                }
            }
            if (classSet == null) {
                return;
            }

            //invok測試
//        User user = new User();
//        user.setName("1222222");
//        user.setYears(120);
//        Object classObject = applicationContext.getBean("userServiceImpl");
//        Object[] objects = new Object[]{user};
//        MethodAccess ma = MethodAccess.get(classObject.getClass());
//        int index = ma.getIndex("getUser");
//        Object obj2 = ma.invoke(classObject, index, objects);
//        System.out.println("obj is " + JSON.toJSONString(obj2));
            //保存到内存
            for (Class<?> instance : classSet) {
                try{
                    String key = instance.getName();
                    Object serviceObject = applicationContext.getBean(instance);
                    RpcRouteInfo rpcRouteInfo = new RpcRouteInfo();
                    rpcRouteInfo.setServicePath(key);
                    rpcRouteInfo.setServiceObject(serviceObject);
                    MethodAccess methodAccess = MethodAccess.get(serviceObject.getClass());
                    rpcRouteInfo.setMethodAccess(methodAccess);

//          暂时不做同方法名不同参数的功能
            List<RpcMethodInfo> rpcMethodInfoList = new ArrayList<>();
            Method[] methods = instance.getMethods();//自定义方法
            for(Method method:methods){
                RpcMethodInfo rpcMethodInfo  = new RpcMethodInfo();
                rpcMethodInfo.setMethod(method.getName());
                rpcMethodInfo.setParamTypes(method.getParameterTypes());
                rpcMethodInfo.setReturnType(method.getReturnType());
                rpcMethodInfoList.add(rpcMethodInfo);
            }
            rpcRouteInfo.setRpcMethodInfoList(rpcMethodInfoList);





                    rpcRouteInfoConcurrentHashMap.put(key, rpcRouteInfo);
                }catch (Exception e){
//                    e.printStackTrace();
                    LOGGER.info("加载失败"+e.getMessage());
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.info("加载失败"+e.getMessage());
        }
    }

    @Override
    public InvokRpcMethod getInvokRpcMethod(InvokRpcMethod invokRpcMethod) throws Exception {
        RpcRouteInfo rpcRouteInfo = rpcRouteInfoConcurrentHashMap.get(invokRpcMethod.getServicePath());
        if (rpcRouteInfo == null) {
            return null;
        }
        invokRpcMethod.setServiceObject(rpcRouteInfo.getServiceObject());
        invokRpcMethod.setMethodAccess(rpcRouteInfo.getMethodAccess());
        return invokRpcMethod;
    }

    @Override
    public Object methodInvoke(InvokRpcMethod invokRpcMethod) throws Exception {
//        MethodAccess ma2 =rpcRouteInfo.getMethodAccess();
//        index = ma2.getIndex("getUser");
//        Object obj3= ma2.invoke(classObject, index, objects);
//        System.out.println("obj is " + JSON.toJSONString(obj3));
        MethodAccess ma = invokRpcMethod.getMethodAccess();
        //暂时不定义参数，不存在同方法不同属性
//        int index = ma.getIndex(invokRpcMethod.getMethod(), invokRpcMethod.getParamTypes());
//        int index = ma.getIndex(invokRpcMethod.getMethod());

        //方法和入参参数
        int index = ma.getIndex(invokRpcMethod.getMethod(),invokRpcMethod.getParamTypes());
        Object obj = ma.invoke(invokRpcMethod.getServiceObject(), index, invokRpcMethod.getParamDatas());
        return obj;
    }
}
